
package com.soxing.webrain.brush.service.docker;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.model.*;
import com.soxing.webrain.brush.service.webSocket.WebSocketServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.soxing.webrain.brush.dao.entity.Task;

import javax.annotation.Resource;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.File;

@Service
public class MyDockerClient {
    @Resource
    DockerClient dockerClient;

    private static final Logger logger = LoggerFactory.getLogger(MyDockerClient.class);

    public String exec(String mountPath, String cmd,String imagePath,String id, Integer status) throws Exception {

        logger.info("执行算法:"+ " 执行命令 "+ cmd + " 镜像名称 "+imagePath);

        CreateContainerResponse container;
        try{
            String[] nowcmd;
            //以空格分割参数
            if(cmd != null){
                String[] cmds = cmd.split(" ");
                nowcmd = new String[cmds.length];
                for(int i=0;i<cmds.length;i++){
                    nowcmd[i] = cmds[i];
                }
            }else{
                nowcmd = null;
            }
//            nowcmd[0] = "stdbuf";
//            nowcmd[1] = "-oL";

            //input路径包含具体文件名，获取该文件的父目录挂载进入容器中
            // String inputDirect = input.substring(0,input.lastIndexOf('/'));
            //容器内部路径与宿主机路径保持一致

            File dataDir = new File(mountPath + "data/" + id);
            if (!dataDir.exists()) {
                dataDir.mkdirs(); // 创建目录
            }
            File resultsDir = new File(mountPath + "results/" + id);
            if (!resultsDir.exists()) {
                resultsDir.mkdirs(); // 创建目录
            }

            String mount = mountPath+":" + "/FB";
            Bind[] binds = new Bind[1];
            binds[0] = Bind.parse(mount);

            // 创建容器
//            container = dockerClient.createContainerCmd(imagePath)
//                    .withCmd(nowcmd)
//                    .withHostConfig(newHostConfig().withBinds(binds))
//                    .exec();
            container = dockerClient.createContainerCmd(imagePath)
                    .withHostConfig(
                            new HostConfig()
                                    .withNetworkMode("host")
                                    .withPrivileged(true)
                                    .withAutoRemove(true)
                                    .withBinds(binds)
                    )
                    .withCmd(nowcmd)
                    .withAttachStdin(true)
                    .withAttachStdout(true)
                    .withAttachStderr(true)
                    .withTty(true)
                    .exec();

            //启动容器
            dockerClient.startContainerCmd(container.getId())
                    .exec();

            if(status == 0) {
                // 获取容器日志
                new Thread(() -> {
                    try {
                        dockerClient.attachContainerCmd(container.getId())
                                .withStdOut(true)
                                .withStdErr(true)
                                .withFollowStream(true)
                                .withLogs(true)
                                .exec(new ResultCallback.Adapter<Frame>() {
                                    @Override
                                    public void onNext(Frame frame) {
                                        System.out.print(new String(frame.getPayload()));
                                        String logMessage = new String(frame.getPayload());
                                        logger.info(logMessage);
                                        // websocket发送日志到前端
                                        WebSocketServer.sendDockerLog(logMessage);
                                    }
                                }).awaitCompletion();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }).start();
            } else if (status == 6) {
                // 等待运行完成
                dockerClient.waitContainerCmd(container.getId()).start().awaitCompletion();
            }


        }catch (Exception e){
            // 如果失败在日志中记录错误信息
            logger.error("执行算法发生异常:" + e.getMessage());
            return null;
        }

        // 如果成功返回容器的ID用于后续的业务逻辑调用
        return container.getId();
    }

    public String createJob(Task p, String image) throws Exception {

        // List<Container> containers = dockerClient.listContainersCmd().exec();

        String containerId = null;
        containerId = exec(p.getMountPath(),"--input " + p.getInput() + " --output " + p.getOutput(), image, Long.toString(p.getId()), p.getStatus());

        logger.info(containerId);

        return containerId;
    }

    public String createReportJob(Task p,String imageName, String image) throws Exception {

        String containerId = null;
        containerId = exec(p.getMountPath(), "/root/matlab_script/" + imageName + " " + p.getOutput(), image, Long.toString(p.getId()), p.getStatus());

        logger.info(containerId);

        return containerId;
    }

    public Boolean stopJob(String containerId) {
        try {
            // 停止容器
            dockerClient.stopContainerCmd(containerId).exec();
            System.out.println("Container " + containerId + " has been stopped.");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public Boolean clearContainers(String image) {
        try {
            // 查找正在运行的容器
            ProcessBuilder processBuilder = new ProcessBuilder("docker", "ps", "-q", "--filter", "ancestor=" + image);
            Process process = processBuilder.start();

            // 读取输出
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    if (!line.trim().isEmpty()) {
                        // 停止容器
                        stopContainerById(line.trim());
                    }
                }
            }
            // 等待命令执行完成
            int exitCode = process.waitFor();
            if (exitCode != 0) {
                System.err.println("Failed to find containers with image " + image);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private static void stopContainerById(String containerId) throws IOException, InterruptedException {
        ProcessBuilder stopProcessBuilder = new ProcessBuilder("docker", "stop", containerId);
        Process stopProcess = stopProcessBuilder.start();
        int exitCode = stopProcess.waitFor();
        if (exitCode == 0) {
            System.out.println("Container with ID " + containerId + " has been stopped.");
        } else {
            System.err.println("Failed to stop container with ID " + containerId);
        }
    }
}
